/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Copyright 2002-2003 by Mark Wolgemuth, All rights reserved.             */
/* Copyright 2002-2003 by Employease, Inc.  All rights reserved.           */
/*                                                                         */
/* Redistribution and use in source and binary forms, with or without      */
/* modification, are permitted provided that the following conditions      */
/* are met:                                                                */
/*                                                                         */
/*    1. Redistributions of source code must retain the above copyright    */
/* notice, this list of conditions and the following disclaimer.           */
/*    2. Redistributions in binary form must reproduce the above copyright */
/* notice, this list of conditions and the following disclaimer in the     */
/* documentation and/or other materials provided with the distribution.    */
/*                                                                         */
/* THIS SOFTWARE IS PROVIDED BY THE MOD_ATHENA PROJECT ``AS IS'' AND ANY   */
/* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE       */
/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR      */
/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR        */
/* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   */
/* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,     */
/* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR      */
/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY     */
/* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT            */
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE   */
/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.    */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include "ath.h"

void
ath_farm_update(apr_pool_t *pool, ath_farm *farm, ath_upd_farm *farm_upd)
{
    ath_lock *lock;
    ath_node *listctx2, *listctx3;
    ASSERT(farm);
    ASSERT(farm_upd);

    lock = ath_lock_for_idx(farm->lock_idx);
    ath_lock_acquire(lock);
    if (farm_upd->on_u)
	farm->on = farm_upd->on;
    if (farm_upd->str_algo != NULL)
      {
	  char *val;
	  val = apr_pstrdup(pool, farm_upd->str_algo);
	  ath_algo_def_from_str(farm->algo_def, val);
      }
    ath_list_rewind_r(farm_upd->member_add, &listctx2);
    while (ath_list_hasnext_r(farm_upd->member_add, &listctx2))
      {
	  ath_phys *phys = (ath_phys *) 
	    ath_list_getnext_r(farm_upd->member_add, &listctx2);
	  ath_farm_add_member(farm, phys);
      }
    ath_list_rewind_r(farm_upd->member_rem, &listctx3);
    while (ath_list_hasnext_r(farm_upd->member_rem, &listctx3))
      {
	  ath_phys *phys = (ath_phys *) 
	    ath_list_getnext_r(farm_upd->member_rem, &listctx3);
	  ath_farm_remove_member(farm, phys);
      }
    if (farm_upd->hit_adds_to != (int) ATH_ALGO_NON)
      {
	  farm->hit_adds_to = farm_upd->hit_adds_to;
	  farm->hit_adds = farm_upd->hit_adds;
      }
    if (farm_upd->expect_u)
	farm->expect_update = farm_upd->expect;
    if (farm_upd->ttl_u)
	farm->allow_ttl = farm_upd->ttl;
    if (farm_upd->rttl_u)
	farm->recover_ttl = farm_upd->rttl;
    if (farm_upd->smartfarmable_u)
	farm->smartfarmable = farm_upd->smartfarmable;
    if (farm_upd->str_down_url != NULL)
	ath_shm_strncpy(farm->down_url, 
			farm_upd->str_down_url, ATH_NAME_MAX);
    if (farm_upd->str_offline_url != NULL)
	ath_shm_strncpy(farm->offline_url, 
			farm_upd->str_offline_url, ATH_NAME_MAX);
    ath_lock_release(lock);
}

/* see ath_farm_clone_from_str
   this function only contains shm safe part of copy */
ath_farm *
ath_farm_from_str(apr_pool_t *pool, char *str_farm)
{
    ath_farm *farm = NULL;
    ath_lock *lock;
    int idx, i;
    ath_farm *farm_mirr = NULL;
    ath_engine *engine = ath_engine_get();
    ASSERT(str_farm != NULL);

    farm_mirr = ath_farm_clone_from_str(pool, str_farm);
    
    /* we do not allow -1 idxs here, must be shm idxed farm */
    /* will always overwrite corresponding index */
    if ((farm_mirr)
	&& ((farm_mirr->idx < 0) || (farm_mirr->idx > engine->farm_count)))
      {
	  ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
		       "Farm index out of bounds: [%d]", farm_mirr->idx); 
	  farm_mirr = NULL;
      }
    /* work on temp farm obj until valid */
    if (farm_mirr)
	farm = ath_farm_raw_for_idx(farm_mirr->idx);
    if (farm)
      {
	  if ((farm->lock_idx < 0) 
	      || (farm->lock_idx > ath_lock_mux_init_count()))
	      ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
			   "Impossible lock idx: [%d]", farm->lock_idx); 
	  else
	    {
		lock = ath_lock_for_idx(farm->lock_idx);
		ath_lock_acquire(lock);
		ath_farm_copy(farm, farm_mirr);
		ath_lock_release(lock);
	    }
      }
    else
	ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, ATH_EFARMSTR);

    return farm;
}
